// (C) 2022 Intel Corporation. All rights reserved.
// Your use of Intel Corporation's design tools, logic functions and other 
// software and tools, and its AMPP partner logic functions, and any output 
// files from any of the foregoing (including device programming or simulation 
// files), and any associated documentation or information are expressly subject 
// to the terms and conditions of the Intel Program License Subscription 
// Agreement, Intel FPGA IP License Agreement, or other applicable 
// license agreement, including, without limitation, that your use is for the 
// sole purpose of programming logic devices manufactured by Intel and sold by 
// Intel or its authorized distributors.  Please refer to the applicable 
// agreement for further details.

`include "mainfpga_version.vh"

module master_fub
(
    input           iClk,
    input           iRst_n,

    input           iLTPI_LINK_ALIGNED,                             // From IOC module, indicate LTPI link training done, link aligned
    input           iSYS_CHECK_OK,                                  // From sys_check, indicate processor ID and package ID match the correct configuration
    input           iINTR_PRSNT_N,
    input           iBMC_ONCTL_N,                                   // From BMC through LVDS, indicate BMC is controlling the sequence
    input           iFM_SLP_S3_N,                                   // From CPU0, indicate system is in ACPI S3 state to control all non-critical components
    input           iFM_SLP_S4_N,                                   // From CPU0, indicate system is in ACPI S4 state to control DRAM and all core power
    input           iFM_HPM_STBY_EN,                                // From DC-SCM, indicate all VRs of DC-SCM modules are on, including DC-SCM card VRs and runBMC VRs
    input           iFM_HPM_STBY_RST_N,                             // From DC-SCM, indicate BMC boot done

    input           iCpu0AuxPwrgdPfr,                               //This comes from PFR and helps indicating special FW update flow (need to be used to go to S5 and toggle S5_PWR_RETAINED and CPU_AUX_PWRGD output)
 
    input           iSTBY_PWRGD,                                    // From baseboard stand-by VRs,indicate baseboard stand-by VRs on, including P5V_AUX, P3V3_AUX and P1V8_AUX
    input           iCPU0_AUX_Done,                                 // From cpu0_aux, indicate all VRs of legacy CPU AUX domain are on           
    input           iCPU1_AUX_Done,                                 // From cpu1_aux, indicate all VRs of legacy CPU AUX domain are on           	
    input           iPSU_Done,                                      // From psu_ctrl, indicate power supply unit main power domain are on
    input           iCPU0_MEM_Done,                                 // From cpu_mem_seq, indicate all VRs of CPU0 main domain are on 
    input           iCPU1_MEM_Done,                                 // From cpu_mem_seq, indicate all VRs of CPU1 main domain are on 
    input           iSCM_BMC_FLT,                                   // From BMC through LVDS, indicate power failure of DC-SCM modules, including DC-SCM card VRs or runBMC VRs
    input           iCPU_AUX_FLT,                                   // From cpu0_aux, indicate power failure of legacy CPU AUX domain
    input           iPSU_FLT,                                       // From psu_ctrl, indicate power failure of power supply unit main power domain, including P5V or P3V3 VRs
    input           iPSU_PWROK_FLT,                                 // From psu_ctrl, indicate power failure is due to PSU
    input           iCPU_PWR_FLT,                                   // From cpu_mem_seq, indicate power failure of CPU main power domain
    input           iVR_PWROFF_TIMEOUT,                             // From cpu_mem_swq, indicate timeout error during certain VR power off
    input           iSOCKET_REMOVED,                                // From sys_check, indicate CPU is removed during runtime
    input           iCPU_AUX_VR_PWROFF_ERR,                         // From cpu_aux, indicate timeout error during certain VR power off
    input           iCPU0_DIMM_FAULT,                               // From ddr5_pwrgd_logic, indicate power failure of CPU0 DIMM
    input           iCPU1_DIMM_FAULT,                               // From ddr5_pwrgd_logic, indicate power failure of CPU1 DIMM

    input           iRST_PLD_PCIE_CPU0_DEV_PERST_R_N,               // From perst, indicate CPU0 PCIe devices reset driving by inband reset flows
    input           iRST_PLD_PCIE_CPU1_DEV_PERST_R_N,               // From perst, indicate CPU1 PCIe devices reset driving by inband reset flows
    input           iFM_GLBRST_WARN_N,                              // From CPU0, indicate a global reset will be taken
    input           iFM_THERMTRIP_N,                                // From CPU, indicates processor or memory has reached a temperature beyond which permanent silicon damage may occur
    input           iPLTRST_SYNC_N,                                 // From CPU after PFR filtering, indicate to the platform to reset platform functions
    input           iFM_CPU0_REFCLK_RDY,                            // From CPU0, indicate CPU0 reference clock is ready
    input           iFM_CPU1_REFCLK_RDY,                            // From CPU1, indicate CPU1 reference clock is ready
    input           iSURPRISE_RESET,                                // From BMC through LVDS and sGPIO, indicate a warm reset triggered by BMC
    input           iFM_GLOBAL_RESET,                               // From BMC through LVDS and sGPIO, indicate a global reset triggered by BMC
    input           iFM_SERIAL_BOOT,                                // From on-board jumper J8C1, indicate boot mode. HIGH (default) for serial boot and LOW for parallel boot
    input           iFM_CPU1_SKTOCC_LVT3_PLD_N,                     // From CPU1, indicate socket 1 occupation
    input           iFM_ADR_MODE0,                                  // From BIOS through vGPIO, indicate ADR mode
    input           iFM_ADR_MODE1,                                  // From BIOS through vGPIO, indicate ADR mode
    input           iADR_ACK_N,                                     // From ADR fub, indicate power down is triggered by ADR flow
    input           iPWR_RESTART,                                   // From BMC through CSR, force to exit power failure state
    input           iFORCE_TO_ENTER_ERR,                            // From BMC through CSR, force to enter power failure state
    input           iGLBRST_HOLD_OFF,                               // From BMC through CSR, hold off Global Reset flow
    input           iCPU0_AUX_PWRGD_POSEDGE,                        // From PFR filtered, use this rising edge for S5_PWR_RETAINED sample
    input           iCpu1IntrClkConfDone,                           // Used when interposer is present
	input           iMEM_PWR_OK,                                    // To know when PVCCD is turned off during Power Down
	input           iPWRGD_PVNN_MAIN_CPU0,							// For S5_PWR_RETAINED

    output reg      oCPU0_AUX_EN,                                   // To cpu0_aux, enable legacy CPU AUX power domain
    output reg      oCPU1_AUX_EN,                                   // To cpu_mem_seq, enable non-legacy CPU AUX power domain
    output reg      oPSU_EN,                                        // To psu_ctrl, enable power supply unit main power domain
    output reg      oCPU_MEM_EN,                                    // To cpu_mem_seq, enable CPU main power domain and memory power domain
    output reg      oADR_EN,                                        // To adr_fub, enable ADR flow
    output reg      oADR_RELEASE,                                   // To ddr5_pwrgd_logic, indicate use ddr5 logic or ADR logic to drive DRAM power sequence
    output          oAUX_PWRGD_CPU0,                                // To CPU0, indicate all VRs of legacy CPU AUX domain are on
    output          oAUX_PWRGD_CPU1,                                // To CPU1, indicate all VRs of non-legacy CPU AUX domain are on
    output          oFM_HPM_STBY_RDY,                               // To DC-SCM, indicate baseboard stand-by VRs on
    output          oDDR_GLBRST_THERMTRIP_DOWN,                     // To ddr5_pwrgd_logic, enable DIMM power down
    output          oS0_PWROK_CPU0,                                 // To CPU0, indicate S0 power rails on platform are up and stable
    output          oS0_PWROK_CPU1,                                 // To CPU1, indicate S0 power rails on platform are up and stable (Reserve for partition usage)
    output reg      oPWRGD_CPU0,                                    // To CPU0, indicate all VRs of legacy CPU domain are on
    output          oPWRGD_CPU1,                                    // To CPU1, indicate all VRs of non-legacy CPU domain are on (Reserve for partition usage)

    output          oRST_CPU0_RESET_N,                              // To CPU0, trigger CPU0 reset
    output          oRST_CPU1_RESET_N,                              // To CPU1, trigger CPU1 reset (Reserve for partition usage)
    output reg      oPWR_RESTART_CLEAR,                             // To global CSR, clear BMC indication
    output reg      oS5_PWR_RETAINED,                               // To CPU0, indicate VNN power retained
    output reg      oFORCE_TO_ENTER_ERR_CLEAR,                      // To global CSR, clear BMC indication
    output reg      oCLEAR_ERROR_STATE,                             // To S0 power domain control module, force to clear power failure status

    output    [3:0] oMASTER_POST_CODE,                              // To debug FPGA through sGPIO, display postcode on 7-segment LED
    output reg[3:0] pwr_err_source,                                 // To global CSR, indicate power failure source
    output reg[2:0] CurrentTime_Masterfub,                           // To debug FPGA, indicate platform sequence stage
	
     input iSMB_PCIE_STBY_LVC3_SCL,
	input 			iLegacyNode,
	input			iwInModular,
	input 			iwInRP,
    input           rjo_ready,
    input           rjo_ready_sec,
	
	
	output  oMBVR_ready_sync,
    input   iMBVR_ready_ack
	
);

/*************************************************************************************************************
 * Local Parameter Definitions                                                                               *
 *************************************************************************************************************/
    localparam LOW  = 1'b0;
    localparam HIGH = 1'b1;

    localparam ST_INIT              = 4'd0;         // 0.0.
    localparam ST_SCM_AUX           = 4'd1;         // 0.1.
    localparam ST_BMC_BOOT          = 4'd2;         // 0.2.
    localparam ST_LCPU_AUX          = 4'd3;         // 0.3.
    localparam ST_PSU               = 4'd4;         // 0.4.
    localparam ST_CPU_MEM           = 4'd5;         // 0.5.
    localparam ST_S0_PWROK          = 4'd6;         // 0.6.
    localparam ST_CPU_PWRGD         = 4'd7;         // 0.7.
    localparam ST_CPU_RESET         = 4'd8;         // 0.8.
    localparam ST_PLATFORM_ON       = 4'd9;         // 0.9.
    localparam ST_ERROR             = 4'd10;        // 0.a.
    localparam ST_ADR               = 4'd11;        // 0.b.

    localparam Runtime              = 3'd0;
    localparam WARM_RESET           = 3'd1;
    localparam COLD_RESET           = 3'd2;
    localparam GLOBAL_RESET         = 3'd3;
    localparam T_RESET              = 3'd4;

    localparam ERR_NO               = 4'd0; // No error
    localparam ERR_SCM_AUX          = 4'd1; // Indicate DC-SCM and RunBMC VR error
    localparam ERR_LCPU_AUX         = 4'd2; // Indicate legacy processor AUX power error
    localparam ERR_GLBRST_S5        = 4'd3; // Indicate S5 global reset second assertion error
    localparam ERR_THERMTRIP        = 4'd4; // Indicate Thermtrip and Memtrip error
    localparam ERR_MAIN_PWR         = 4'd5; // Indicate main power error, including PSU main power error, processor main power errors and non-legacy processor AUX power error
    localparam ERR_TIMEOUT          = 4'd6; // Indicate VR power off timeout error
    localparam ERR_FORCE_ENTER      = 4'd7; // Indicate BMC force to enter error state
    localparam ERR_MBVR_TIMEOUT     = 4'd8; // Indicate power failure flow timeout error
    localparam ERR_LTPI_BROKEN      = 4'd9; // Indicate LTPI link broken
    localparam ERR_OTHER            = 4'd10;// Indicate other failure such as standby power error, socket removed during runtime, etc.

    `ifdef SIMULATION
        localparam T_2uS_2M         = 4'd4;
        localparam T_10uS_2M        = 6'd20;
        localparam T_100uS_2M       = 9'd200;
        localparam T_1mS_2M         = 11'd1000;
		localparam T_2_1mS_2M       = 11'd1000;
        localparam T_2mS_2M         = 11'd1000;
        localparam T_5mS_2M         = 11'd1000;
        localparam T_100mS_2M       = 11'd1000;
        localparam T_500mS_2M       = 11'd1000;
   `else
        localparam T_2uS_2M         = 4'd4;
        localparam T_10uS_2M        = 6'd20;
        localparam T_100uS_2M       = 9'd200;
        localparam T_1mS_2M         = 12'd2000;
		localparam T_2_1mS_2M       = 13'd4200;
        localparam T_2mS_2M         = 13'd4000;
        localparam T_5mS_2M         = 15'd10000;
        localparam T_100mS_2M       = 19'd200000;
        localparam T_500mS_2M       = 21'd1000000;
   `endif 

/*************************************************************************************************************
 * Local Registers and Wires Definitions                                                                     *
 *************************************************************************************************************/
    reg [3:0]   rstate;
    
    reg         rAUX_PWRGD_CPU0;
    reg         rAUX_PWRGD_CPU1;
    reg         rS0_PWROK_CPU0;
    reg         rS0_PWROK_CPU1;
    reg         rcount;
    reg         rRST_CPU0_RESET_N;
    reg         rADR_EN;
    reg         rADR_EMULATED;
    reg         rDDR_PowerDown_En;

    wire        wSTBY_ERR;              // Indicate standby errors, including DC-SCM and RunBMC VR error, baseboard VR failure, legacy processor AUX power error and socket removed during runtime
    wire        wMAIN_PWR_ERR;          // Indicate main power error, including PSU main power error, processor main power errors and non-legacy processor AUX power error
    wire        wTIMEOUT_ERR;           // Indicate timeout error during normal power down
    wire        wMBVR_ERR_local;        // Total power failure indication, go to MBVR failure power down flow
	 wire        wMBVR_ERR;              // Total power failure indication, go to MBVR failure power down flow
    wire        wERR_FLOW_TIMEOUT;      // Indicate timeout error during power failure flow, go to ST_ERROR directly

    reg         rStartTimer_T27;
    reg         rStartTimer_T28;
    reg         rStartTimer_T31;
    reg         rStartTimer_T32;
    reg         rStartTimer_T33;
    reg         rStartTimer_1ms;
    reg         rStartTimer_T55;
    reg         rStartTimer_T56;
    wire        wStartTimer_T16;
    wire        wDoneTimer_T16;         // T16: min 100 ms timer, from PVCCINFAON PWRGD assertion to S0_PWROK assertion
    wire        wDoneTimer_T18;         // T18: min 1 ms timer, from CPU_REFCLK_RDY assertion to CPU_PWRGD assertion
    wire        wStartTimer_T27;        // T27: min 2 ms timer, from RESET# assertion to CPU_PWRGD de-assertion
    wire        wDoneTimer_T27;
    wire        wStartTimer_T28;        // T28: min 1 ms timer, from CPU_PWRGD de-assertion to S0_PWROK de-assertion
    wire        wDoneTimer_T28;
    wire        wStartTimer_T31;        // T31: min 100 us timer, from S0_PWROK de-assertion to non-legacy CPU AUX_PWRGD de-assertion
    wire        wDoneTimer_T31;
    wire        wStartTimer_T32;        // T32: min 5 ms timer, from legacy CPU AUX_PWRGD de-assertion to legacy CPU AUX_PWRGD re-assertion
    wire        wDoneTimer_T32;
    wire        wStartTimer_T33;        // T33: max 500 ms watchdog, from thermtrip# assertion to VCCFA_EHV PWRGD de-assertion
    wire        wDoneTimer_T33;
    wire        wStartTimer_1ms;        // T??: min 1ms timer, from surprise reset assertion to reboot
    wire        wDoneTimer_1ms;
    wire        wStartTimer_T55;        // T55: min 2 us, max 10 us timer, from CPU_PWRGD de-assertion to S0_PWROK de-assertion during MBVR failure flow
    wire        wDoneTimer_T55L;
    wire        wDoneTimer_T55H;
    wire        wStartTimer_T56;        // T56: min 2 us, max 10 us timer, from S0_PWROK de-assertion to AUX_PWRGD de-assertion during MBVR failure flow
    wire        wDoneTimer_T56L;
    wire        wDoneTimer_T56H;
    wire        wDoneTimer_1msB;

    wire        wS3Indication;
    wire        wS4Indication;

    wire        wPWR_DOWN_NORMAL;
    wire        wPWR_DOWN_TOTAL;
    
    wire        wRUNTIME_PWRDWN;
    reg         rFM_GLBRST_WARN_N;
    reg         rFM_GLBRST_WARN_NEGEDGE_N;
    reg         rPLTRST_N;
    reg         rPLTRST_NEGEDGE_N;
    reg         rPLTRST_POS;
    wire        wPLTRST_POS;
    reg         rTHERMTRIP_NEGEDGE_N;
    reg         rTHERMTRIP_N;
    reg         rSURPRISE_RESET0;
    reg         rSURPRISE_RESET1;
    reg         rSURPRISE_POSEDGE;
    reg         rFM_GLOBAL_RESET0;
    reg         rFM_GLOBAL_RESET1;
    reg         rFM_GLOBAL_RESET_POSEDGE;
    reg         rHPM_STBY_EN_NEGEDGE;
    reg         rFM_HPM_STBY_EN;
    reg         rSTBY_PWRGD;
    reg         rSTBY_PWRGD_FLT;
    reg         rLTPI_LINK_ALIGNED;
    reg         rLTPI_LINK_ALIGNED_POSEDGE;
    reg         rVNN_PWRGD;
	wire         wPLTRST_SYNC_N;
	wire	       wFM_CPU0_GLB_RST_WARN_FPGA_LVC18_N_R;
	wire         wFM_GLBRST_WARN_N;
	 reg         mux_sel_glbrst;

/*************************************************************************************************************
 * Logic                                                                                                     *
 *************************************************************************************************************/
	
    assign  oFM_HPM_STBY_RDY            = (iwInModular && !iLegacyNode) ? iFM_HPM_STBY_EN : iCPU0_AUX_Done && iFM_HPM_STBY_EN;        // Baseboard stand-by VRs on (including legacy processor AUX VRs), can release BMC SRST	
	                                                                                                                             
    assign  oS0_PWROK_CPU0              = rS0_PWROK_CPU0;
    assign  oS0_PWROK_CPU1              = iFM_CPU1_SKTOCC_LVT3_PLD_N ? 1'b0 : rS0_PWROK_CPU1;       // In non partition mode, CPU0/1 share same S0_PWROK and gate by SKTOCC_N
    
    assign  oAUX_PWRGD_CPU0             = rAUX_PWRGD_CPU0;
    assign  oAUX_PWRGD_CPU1             = iFM_CPU1_SKTOCC_LVT3_PLD_N ? 1'b0 : rAUX_PWRGD_CPU1;
    assign  oPWRGD_CPU1                 = iFM_CPU1_SKTOCC_LVT3_PLD_N ? 1'b0 : oPWRGD_CPU0;           // In non partition mode, CPU0/1 share same PWRGD_CPU and gate by SKTOCC_N
    assign  oRST_CPU0_RESET_N           = rRST_CPU0_RESET_N;
    assign  oRST_CPU1_RESET_N           = iFM_CPU1_SKTOCC_LVT3_PLD_N ? 1'b0 : rRST_CPU0_RESET_N;    // In non partition mode, CPU0/1 share same CPU_RESET and gate by SKTOCC_N

    assign  oDDR_GLBRST_THERMTRIP_DOWN  = rDDR_PowerDown_En;

    assign  wStartTimer_T16             = iCPU0_MEM_Done && (iFM_CPU1_SKTOCC_LVT3_PLD_N || iCPU1_MEM_Done);
    assign  wStartTimer_T27             = rStartTimer_T27;
    assign  wStartTimer_T28             = rStartTimer_T28;
    assign  wStartTimer_T31             = rStartTimer_T31;
    assign  wStartTimer_T32             = rStartTimer_T32;
    assign  wStartTimer_T33             = rStartTimer_T33;
    assign  wStartTimer_1ms             = rStartTimer_1ms;
    assign  wStartTimer_T55             = rStartTimer_T55;
    assign  wStartTimer_T56             = rStartTimer_T56;

    assign  wS3Indication               = (!iFM_SLP_S3_N && iFM_SLP_S4_N && wDoneTimer_1msB) || (!iFM_SLP_S4_N && rADR_EMULATED && !iADR_ACK_N);// SLP3# asserted and SLP4# de-asserted, we are in S3 state (Support the emulated ADR flow with R-DIMMs)
    assign  wS4Indication               = !iFM_SLP_S4_N && !(rADR_EMULATED && !iADR_ACK_N);         // SLP3# and SLP4# both asserted, we are in S4 state (Support the emulated ADR flow with R-DIMMs)

    assign  wMBVR_ERR_local             = wSTBY_ERR || wMAIN_PWR_ERR || wTIMEOUT_ERR;               // Total power failure indication, go to MBVR failure power down flow

    assign  wPWR_DOWN_NORMAL            = (wS3Indication || wS4Indication) && rPLTRST_NEGEDGE_N || !iCpu0AuxPwrgdPfr;
    assign  wPWR_DOWN_TOTAL             = (!wFM_GLBRST_WARN_N && iGLBRST_HOLD_OFF) ? rTHERMTRIP_NEGEDGE_N : (wPWR_DOWN_NORMAL || !wFM_GLBRST_WARN_N || rFM_GLOBAL_RESET_POSEDGE || rTHERMTRIP_NEGEDGE_N);   // Mask other power down indications except THERMTRIP# when hold off Global Reset
    assign  wRUNTIME_PWRDWN             = (!wFM_GLBRST_WARN_N && iGLBRST_HOLD_OFF) ? rTHERMTRIP_NEGEDGE_N : (wPWR_DOWN_TOTAL  || rPLTRST_NEGEDGE_N  || rSURPRISE_POSEDGE);      // Mask other power down indications except THERMTRIP# when hold off Global Reset
    
    assign  wPLTRST_POS                 = rPLTRST_POS;

    assign  wSTBY_ERR                   = iSCM_BMC_FLT || iCPU_AUX_FLT || iSOCKET_REMOVED|| rHPM_STBY_EN_NEGEDGE;          // Indicate standby errors, including DC-SCM and RunBMC VR error, baseboard VR failure, legacy processor AUX power error and socket removed during runtime
    assign  wMAIN_PWR_ERR               = (iPSU_FLT && !(rADR_EN && iPSU_PWROK_FLT)) || iCPU_PWR_FLT || iCPU0_DIMM_FAULT || iCPU1_DIMM_FAULT;   // Indicate main power error, including PSU main power error, processor main power errors and non-legacy processor AUX power error
    assign  wTIMEOUT_ERR                = iVR_PWROFF_TIMEOUT || iCPU_AUX_VR_PWROFF_ERR;             // Indicate timeout error during normal power down
    assign  wERR_FLOW_TIMEOUT           = wDoneTimer_T33 || wDoneTimer_T55H || wDoneTimer_T56H;     // Indicate timeout error during power failure flow, go to ST_ERROR directly

    assign  oMASTER_POST_CODE           =  rstate;
	
	assign  wPLTRST_SYNC_N              = oPWRGD_CPU0 ? iPLTRST_SYNC_N : 1'b0;

    assign  oMBVR_ready_sync            = iwInModular ? wMBVR_ERR_local  : 1'b0; // MBVR flow for Modular
    assign  wMBVR_ERR                   = iwInModular ? iMBVR_ready_ack  : wMBVR_ERR_local;

	//This filter is to avoid glitches in GLBRST before AUX_PWRGD assertion
	always @ (posedge iClk or negedge iRst_n) begin
        if (!iRst_n) begin
		   mux_sel_glbrst    <= LOW;
        end	
	    else if (rAUX_PWRGD_CPU0) begin
				mux_sel_glbrst      <= HIGH;
			end else begin
  				mux_sel_glbrst <= mux_sel_glbrst;
				end
        end	
	assign wFM_GLBRST_WARN_N         = mux_sel_glbrst ?  iFM_GLBRST_WARN_N : 1'b1 ;
	
	
	always @ (posedge iClk or negedge iRst_n) begin
        if (!iRst_n) begin
            oS5_PWR_RETAINED    <= LOW;
        end
        else if (!wS4Indication) begin
            oS5_PWR_RETAINED    <= HIGH;                 // In first time power up S5_PWR_RETAINED goes HIGH when SLPS4 is asserted
        end else if (!iPWRGD_PVNN_MAIN_CPU0 || !(rAUX_PWRGD_CPU0 || iCpu0AuxPwrgdPfr) ) begin
            oS5_PWR_RETAINED    <= LOW;                // It only get changed when PWRGD_VNN[L] is de-asserted
        end
    end
	
	
	
	
    always @ (posedge iClk or negedge iRst_n) begin // ADR state machine for interposer
        case ({iFM_ADR_MODE1, iFM_ADR_MODE0})
            2'b00: begin                            // ADR is disabled by processor
               rADR_EN          <= LOW;
               rADR_EMULATED    <= LOW;
            end // case: 2'b00
            2'b01: begin                            // Platform legacy mode
               rADR_EN          <= HIGH;
               rADR_EMULATED    <= LOW;
            end // case: 2'b01
            2'b10: begin
               rADR_EN          <= HIGH;
               rADR_EMULATED    <= HIGH;
            end // case: 2'b10
            2'b11: begin
               rADR_EN          <= LOW;
               rADR_EMULATED    <= LOW;
            end // case: 2'b11
            default: begin
               rADR_EN          <= LOW;
               rADR_EMULATED    <= LOW;
            end // case: default
        endcase
     end
  
    always @ (posedge iClk or negedge iRst_n) begin
        if (!iRst_n) begin
            oCPU0_AUX_EN                <= LOW;
            oCPU1_AUX_EN                <= LOW;
            oPSU_EN                     <= LOW;
            oCPU_MEM_EN                 <= LOW;
            oADR_EN                     <= LOW;
            oADR_RELEASE                <= LOW;
            rS0_PWROK_CPU0              <= LOW;
            rS0_PWROK_CPU1              <= LOW;
            oPWRGD_CPU0                  <= LOW;
            rAUX_PWRGD_CPU0             <= LOW;
            rAUX_PWRGD_CPU1             <= LOW;
            rcount                      <= LOW;
            rDDR_PowerDown_En           <= LOW;
            rRST_CPU0_RESET_N           <= LOW;
            rFM_GLBRST_WARN_NEGEDGE_N   <= LOW;
            rFM_GLBRST_WARN_N           <= LOW;
            rPLTRST_NEGEDGE_N           <= LOW;
            rPLTRST_POS                 <= LOW;
            rPLTRST_N                   <= LOW;
            rStartTimer_T27             <= LOW;
            rStartTimer_T28             <= LOW;
            rStartTimer_T31             <= LOW;
            rStartTimer_T32             <= LOW;
            rStartTimer_T33             <= LOW;
            rStartTimer_1ms             <= LOW;
            rStartTimer_T55             <= LOW;
            rStartTimer_T56             <= LOW;
            rTHERMTRIP_NEGEDGE_N        <= LOW;
            rSURPRISE_RESET0            <= LOW;
            rSURPRISE_RESET1            <= LOW;
            rSURPRISE_POSEDGE           <= LOW;
            rFM_GLOBAL_RESET0           <= LOW;
            rFM_GLOBAL_RESET1           <= LOW;
            rFM_GLOBAL_RESET_POSEDGE    <= LOW;
            oCLEAR_ERROR_STATE          <= LOW;
            oPWR_RESTART_CLEAR          <= LOW;
            oFORCE_TO_ENTER_ERR_CLEAR   <= LOW;
            rLTPI_LINK_ALIGNED          <= LOW;
            rLTPI_LINK_ALIGNED_POSEDGE  <= LOW;
            rFM_HPM_STBY_EN             <= LOW;
            rHPM_STBY_EN_NEGEDGE        <= LOW;
            rSTBY_PWRGD                 <= LOW;
            rSTBY_PWRGD_FLT             <= LOW;
            rTHERMTRIP_N                <= HIGH;
            rstate                      <= ST_INIT;
            pwr_err_source              <= ERR_NO;
            CurrentTime_Masterfub       <= Runtime;
        end
        else begin
            rPLTRST_N                   <= wPLTRST_SYNC_N;
            rFM_GLBRST_WARN_N           <= wFM_GLBRST_WARN_N;
            rTHERMTRIP_N                <= iFM_THERMTRIP_N;
            rSURPRISE_RESET0            <= iSURPRISE_RESET;
            rSURPRISE_RESET1            <= rSURPRISE_RESET0;
            rFM_GLOBAL_RESET0           <= iFM_GLOBAL_RESET;
            rFM_GLOBAL_RESET1           <= rFM_GLOBAL_RESET0;
            rFM_HPM_STBY_EN             <= iFM_HPM_STBY_EN;
            rSTBY_PWRGD                 <= iSTBY_PWRGD;
            rLTPI_LINK_ALIGNED          <= iLTPI_LINK_ALIGNED;

            rFM_GLBRST_WARN_NEGEDGE_N   <= (rFM_GLBRST_WARN_N &&! wFM_GLBRST_WARN_N) ? HIGH : rFM_GLBRST_WARN_NEGEDGE_N;
            rPLTRST_NEGEDGE_N           <= (rPLTRST_N &&! wPLTRST_SYNC_N) ? HIGH : rPLTRST_NEGEDGE_N;
            rPLTRST_POS                 <= (!rPLTRST_N && wPLTRST_SYNC_N) ? HIGH : rPLTRST_POS;
            rTHERMTRIP_NEGEDGE_N        <= (rTHERMTRIP_N &&! iFM_THERMTRIP_N) ? HIGH : rTHERMTRIP_NEGEDGE_N;
            rSURPRISE_POSEDGE           <= (!rSURPRISE_RESET1 && rSURPRISE_RESET0) ? HIGH : rSURPRISE_POSEDGE;
            rFM_GLOBAL_RESET_POSEDGE    <= (!rFM_GLOBAL_RESET1 && rFM_GLOBAL_RESET0) ? HIGH : rFM_GLOBAL_RESET_POSEDGE;
            rHPM_STBY_EN_NEGEDGE        <= (rFM_HPM_STBY_EN && !iFM_HPM_STBY_EN && rLTPI_LINK_ALIGNED_POSEDGE) ? HIGH : rHPM_STBY_EN_NEGEDGE;   // Don't capture negative edge during FPGA configure period
            rSTBY_PWRGD_FLT             <= (rSTBY_PWRGD && !iSTBY_PWRGD) ? HIGH : rSTBY_PWRGD_FLT;
            rLTPI_LINK_ALIGNED_POSEDGE  <= (!rLTPI_LINK_ALIGNED && iLTPI_LINK_ALIGNED) ? HIGH : rLTPI_LINK_ALIGNED_POSEDGE;

            case (rstate)
                ST_INIT: begin
                    if (iLTPI_LINK_ALIGNED && rjo_ready && rjo_ready_sec) begin               // If link training aligned, go to next state
					
						if(iSMB_PCIE_STBY_LVC3_SCL) begin//
                          rstate          <= ST_SCM_AUX;
						  end//
						else begin rstate          <= ST_ERROR;
                             end //
					    end
					else begin
                         rstate          <= rstate;
					     end//
                end // case: ST_INIT

                ST_SCM_AUX: begin
                    oPWR_RESTART_CLEAR          <= LOW;         // If just exit from ERROR state, clear all power failure indication
                    oFORCE_TO_ENTER_ERR_CLEAR   <= LOW;
                    oCLEAR_ERROR_STATE          <= LOW;
                    if (wMBVR_ERR || wERR_FLOW_TIMEOUT) begin
                        rstate                  <= ST_ERROR;
                        end
					else if (iFM_HPM_STBY_EN && (iwInRP || (iwInModular && iLegacyNode) )) begin // BMC boot down, enable legacy CPU AUX power domain and go to next state
                            oCPU0_AUX_EN            <= HIGH;
                            if (!iFM_SERIAL_BOOT) begin // Parallel boot mode
                               rstate              <= ST_LCPU_AUX;
                               end 
							else begin           // Serial boot mode (default)
                                 rstate              <= ST_BMC_BOOT;
						         end
                        end
					
					else if (iFM_HPM_STBY_EN && iwInModular && !iLegacyNode) begin
					        oCPU0_AUX_EN        <= LOW;
					        if (!iFM_SERIAL_BOOT) begin // Parallel boot mode
                               rstate              <= ST_LCPU_AUX;
                            end 
					        else begin                  // Serial boot mode (default)
                                 rstate              <= ST_BMC_BOOT;
					       	    end
					    end 
                end //case: ST_SCM_AUX

                ST_BMC_BOOT: begin
                    oPWR_RESTART_CLEAR          <= LOW;         // If just exit from ERROR state, clear all power failure indication
                    oFORCE_TO_ENTER_ERR_CLEAR   <= LOW;
                    oCLEAR_ERROR_STATE          <= LOW;
                    if (wMBVR_ERR || wERR_FLOW_TIMEOUT) begin // Power failure, go to ERROR state
                       rstate                  <= ST_ERROR;
                    end else if (iFORCE_TO_ENTER_ERR) begin	// BMC force to enter ERROR state
                       rstate                  <= ST_ERROR;
                    end else if (iFM_HPM_STBY_RST_N) begin	// BMC boot done, go to next state
                       rstate                  <= ST_LCPU_AUX;
					   if(wPWR_DOWN_TOTAL) begin 
					     oCPU0_AUX_EN            <= HIGH;
						 end
                       
                    end
                end //case: ST_BMC_BOOT

                ST_LCPU_AUX: begin
                   rPLTRST_NEGEDGE_N <= LOW;
                    if (wMBVR_ERR || wERR_FLOW_TIMEOUT || rTHERMTRIP_NEGEDGE_N) begin // Power failure
                        if (wERR_FLOW_TIMEOUT) begin // Indicate timeout error during power failure flow, go to ST_ERROR directly
                            rstate              <= ST_ERROR;
                        end else begin // MBVR failure flow
                            rstate              <= ST_PSU;
                            oCPU0_AUX_EN        <= LOW;
                            rAUX_PWRGD_CPU0     <= LOW;
                            rAUX_PWRGD_CPU1     <= LOW;
                            rStartTimer_T56     <= LOW;
                        end
                    end else if (rADR_EN && iPSU_FLT && iPSU_PWROK_FLT) begin // Suprise shut down, enable ADR flow
                        rstate                  <= ST_ADR;
                    end 
                    else if (rFM_GLBRST_WARN_NEGEDGE_N || rFM_GLOBAL_RESET_POSEDGE) begin // S5 global reset
                        if (!rcount) begin // Detect global reset warning for the first time
                            rAUX_PWRGD_CPU0     <= LOW;
                            rStartTimer_T32     <= HIGH;
                            if (wDoneTimer_T32) begin
                                rcount          <= HIGH;
                                rStartTimer_T32 <= LOW;
                                rAUX_PWRGD_CPU0 <= HIGH;
                                rFM_GLBRST_WARN_NEGEDGE_N <= LOW;
                                rFM_GLOBAL_RESET_POSEDGE  <= LOW;
                            end else begin
			                   rstate          <= rstate;
                               end 
						end else if (rcount) begin // Detect global reset warning
							 rstate          <= ST_ERROR;
                            end

                    end else if (!iFM_HPM_STBY_RST_N && iFM_SERIAL_BOOT) begin 
                        rstate                  <= ST_BMC_BOOT;
                        rAUX_PWRGD_CPU0         <= LOW;
                    end else if (!iCpu0AuxPwrgdPfr) begin
                        rAUX_PWRGD_CPU0         <= LOW;
					end else if (iCPU0_AUX_Done && iSYS_CHECK_OK && !wPWR_DOWN_TOTAL && !iFM_SLP_S4_N) begin //(required for IBL card to start moving and eventually deassert slp signals (hence BMC to assert ONCTL_N)
						rAUX_PWRGD_CPU0          <= HIGH;
                    end else if (iCPU0_AUX_Done && !iBMC_ONCTL_N &&  iSYS_CHECK_OK && !wPWR_DOWN_TOTAL && iFM_SLP_S4_N) begin // Legacy CPU AUX power domain on, BMC is on control signal, platform is not in any sleep state
						rAUX_PWRGD_CPU0         <= HIGH;                               //assert CPU0 AUX PWRGD
                        rstate                  <= ST_PSU;
                        oPSU_EN                 <= HIGH;
                        oADR_RELEASE            <= HIGH;                                // ADR logic indicate DIMM to select power down signals from its own logic, not from ADR logic
            
		
					end else if (iwInModular && !iLegacyNode  && !iBMC_ONCTL_N &&  iSYS_CHECK_OK && !wPWR_DOWN_TOTAL) begin // Legacy CPU AUX power domain on, BMC is on control signal, platform is not in any sleep state
                        rstate                  <= ST_PSU;
                        oPSU_EN                 <= HIGH;
                        oADR_RELEASE            <= HIGH;                                // ADR logic indicate DIMM to select power down signals from its own logic, not from ADR logic
                    end
                end // case: ST_LCPU_AUX

                ST_PSU: begin
                    if (wMBVR_ERR || wERR_FLOW_TIMEOUT || rTHERMTRIP_NEGEDGE_N) begin // Power failure
                        oPSU_EN                 <= LOW;
                        rstate                  <= ST_ERROR;                            // MBVR failure flow enter ST_ERROR from here
                    end else if (wPWR_DOWN_TOTAL ) begin // In power down flow
                            oPSU_EN                     <= LOW;
                               if (!rAUX_PWRGD_CPU0) begin // S0 global reset 
                                  rstate                  <= ST_LCPU_AUX;
				                  rFM_GLOBAL_RESET_POSEDGE <= LOW;
                               end else if (wPWR_DOWN_NORMAL) begin // Normal power off
                                   rstate                  <= ST_LCPU_AUX;
                               end else if(!wFM_GLBRST_WARN_N)begin 
                                  rstate                  <= ST_LCPU_AUX;
                                  rAUX_PWRGD_CPU0         <= LOW;								  
							   end
							   
                    end else begin
 					    if (iPSU_Done) begin // PSU main power domain are on, go to next state
						   if( (iwInRP || (iwInModular && iLegacyNode)) && !iFM_CPU1_SKTOCC_LVT3_PLD_N)begin
						        oCPU1_AUX_EN                <= HIGH;
							    if( iCPU1_AUX_Done) begin
							           rAUX_PWRGD_CPU1         <= HIGH;
							   		rstate                  <= ST_CPU_MEM;
							           oCPU_MEM_EN             <= HIGH;
							           rDDR_PowerDown_En       <= LOW;
							         end
						        end 

						   else if(iwInModular && !iLegacyNode ) begin
						          oCPU0_AUX_EN                <= HIGH;
							      oCPU1_AUX_EN                <= HIGH;
								  if(iCPU0_AUX_Done && iCPU1_AUX_Done) begin
						             rAUX_PWRGD_CPU0         <= HIGH;
							         rAUX_PWRGD_CPU1         <= HIGH;
					                 rstate                  <= ST_CPU_MEM;
                                     oCPU_MEM_EN             <= HIGH;
							         rDDR_PowerDown_En       <= LOW;
							        end	 
					            end	
								
							else begin 
							      rstate                      <= ST_CPU_MEM;
							      oCPU_MEM_EN                 <= HIGH;
								  rDDR_PowerDown_En           <= LOW;
								  end
                        end // (iPSU_Done) 
						
						
					end 
					
                end // case: ST_PSU

                ST_CPU_MEM: begin
                    if (wMBVR_ERR || wERR_FLOW_TIMEOUT) begin // Power failure
                        if (wERR_FLOW_TIMEOUT) begin // Indicate timeout error during power failure flow, go to ST_ERROR directly
                            rstate                  <= ST_ERROR;
                        end else begin // MBVR failure flow
                            oCPU_MEM_EN             <= LOW;
                            oCPU1_AUX_EN            <= LOW;
                            rStartTimer_T56         <= HIGH;
                            if (wDoneTimer_T56L) begin // Motherboard VR Failure
                                rstate              <= ST_LCPU_AUX;
                                rDDR_PowerDown_En   <= HIGH;
                                rAUX_PWRGD_CPU1     <= LOW;
                                rStartTimer_T31     <= LOW;
                                rStartTimer_T56     <= LOW;
                            end
                        end // else: !if(wERR_FLOW_TIMEOUT)

                     end // if (wMBVR_ERR || wERR_FLOW_TIMEOUT)
                     else if (wPWR_DOWN_TOTAL) begin 
                        oCPU_MEM_EN            <= LOW;
                        rDDR_PowerDown_En      <= HIGH;
                        if (wDoneTimer_T31 && !iCPU0_MEM_Done && (!iCPU1_MEM_Done || iFM_CPU1_SKTOCC_LVT3_PLD_N)) begin //s0_pwrok timer expired and CPU Main sequencers are done
                           rAUX_PWRGD_CPU1           <= LOW;
                           oCPU1_AUX_EN               <= LOW;                //shutdwn CPU1 AUX VRs
                           if (rTHERMTRIP_NEGEDGE_N) begin
                              rAUX_PWRGD_CPU0         <= LOW;
                              oCPU0_AUX_EN            <= LOW;                //shutdwn CPU0 AUX VRs too
                              rstate                  <= ST_LCPU_AUX;
                           end
                           else if ((!iFM_GLBRST_WARN_N || rFM_GLOBAL_RESET_POSEDGE) && (!iCPU1_AUX_Done || iFM_CPU1_SKTOCC_LVT3_PLD_N)) begin
                              rAUX_PWRGD_CPU0         <= LOW;
                              rStartTimer_T32         <= HIGH;
                              oADR_EN                 <= LOW;
							  if(!iFM_SLP_S4_N)begin
                              rstate                  <= ST_PSU;
							  end
                           end
                           else if (wPWR_DOWN_NORMAL && (!iCPU1_AUX_Done || iFM_CPU1_SKTOCC_LVT3_PLD_N)) begin
                              rstate                 <= ST_PSU;
                              oADR_EN                <= LOW;
                           end
                           else if (!wDoneTimer_T31 && (!wFM_GLBRST_WARN_N || rFM_GLOBAL_RESET_POSEDGE)) begin // This conditional is to recognize GLBRST triggered
                            rStartTimer_T31         <= HIGH;
                        end
					end

                    end else if (iCPU0_MEM_Done && (iFM_CPU1_SKTOCC_LVT3_PLD_N || iCPU1_MEM_Done) && wDoneTimer_T16) begin               // All VRs of CPU0 and CPU1 main domain are on and T16 done, go to next state
                        rstate                  <= ST_S0_PWROK;
                        rS0_PWROK_CPU0          <= HIGH;
                        rS0_PWROK_CPU1          <= HIGH;
                        oADR_EN                 <= rADR_EN;                             // Enable ADR if jumper is not set on board
                    end
                end // case: ST_CPU_MEM

                ST_S0_PWROK: begin
                    if (wMBVR_ERR || wERR_FLOW_TIMEOUT) begin // Power failure
                        if (wERR_FLOW_TIMEOUT) begin // Indicate timeout error during power failure flow, go to ST_ERROR directly
                            rstate                  <= ST_ERROR;
                        end else begin // MBVR failure flow
                            rstate                  <= ST_CPU_MEM;
                            rS0_PWROK_CPU0          <= LOW;
                            rS0_PWROK_CPU1          <= LOW;
                        end
                    end else if (wPWR_DOWN_TOTAL) begin // In power down flow
                        if (wDoneTimer_T28) begin // T28 done
                            rStartTimer_T28         <= LOW;
                            rS0_PWROK_CPU0          <= iRST_PLD_PCIE_CPU0_DEV_PERST_R_N ? rS0_PWROK_CPU0 : LOW;
                            rS0_PWROK_CPU1          <= iRST_PLD_PCIE_CPU0_DEV_PERST_R_N ? rS0_PWROK_CPU1 : LOW;
                            if (!rS0_PWROK_CPU0 && !rS0_PWROK_CPU1) begin
                                rStartTimer_T31     <= HIGH;
                                rstate              <= ST_CPU_MEM;
                            end
                        end else if (!wDoneTimer_T28 && (!wFM_GLBRST_WARN_N || rFM_GLOBAL_RESET_POSEDGE)) begin //This conditional is to recognize GLBRST triggered
                            rStartTimer_T28         <= HIGH;
                        end
                    end else if ((iFM_CPU0_REFCLK_RDY && wDoneTimer_T18 && iINTR_PRSNT_N) || !(iFM_CPU0_REFCLK_RDY || iINTR_PRSNT_N)) begin  // CPU0 reference clock is ready, go to next state
                        rstate                      <= ST_CPU_PWRGD;
                        oPWRGD_CPU0                  <= HIGH;
                    end
                end // case: S0_PWROK

                ST_CPU_PWRGD: begin
                    if (wMBVR_ERR || wERR_FLOW_TIMEOUT) begin // Power failure
                        if (wERR_FLOW_TIMEOUT) begin // Indicate timeout error during power failure flow, go to ST_ERROR directly
                            rstate                  <= ST_ERROR;
                        end else begin // MBVR failure flow
                            rStartTimer_T55         <= HIGH;
                            if (wDoneTimer_T55L) begin // Motherhood VR failure
                                rstate              <= ST_CPU_MEM;
                                rS0_PWROK_CPU0      <= LOW;
                                rS0_PWROK_CPU1      <= LOW;
                                rStartTimer_T55     <= LOW;
                                rStartTimer_T56     <= HIGH;
                            end
                        end
                    end else if (wPWR_DOWN_TOTAL) begin // In power down flow
                        if (rTHERMTRIP_NEGEDGE_N)begin // Thermal trip
                            rstate                  <= ST_CPU_MEM;
                            oPWRGD_CPU0              <= LOW;
                            rS0_PWROK_CPU0          <= LOW;
                            rS0_PWROK_CPU1          <= LOW;
                        end else if (wDoneTimer_T27 && (wPWR_DOWN_NORMAL || !wFM_GLBRST_WARN_N || rFM_GLOBAL_RESET_POSEDGE)) begin // Other power down and T27 done
                            rStartTimer_T27         <= LOW;
                            rStartTimer_T28         <= HIGH;
                            rstate                  <= ST_S0_PWROK;
                            oPWRGD_CPU0              <= LOW;
                        end else if (!wDoneTimer_T27 && ( !wFM_GLBRST_WARN_N || rFM_GLOBAL_RESET_POSEDGE)) begin //This conditional is to recognize GLBRST triggered
                            rStartTimer_T27         <= HIGH;
                        end
                    end else if (wPLTRST_POS) begin // Platform is out of reset, go to next state                    
                        rstate                      <= ST_CPU_RESET;
                    end
                end // case: ST_PLTRST

                ST_CPU_RESET: begin	
                    if (wMBVR_ERR || wERR_FLOW_TIMEOUT) begin // Power failure
                        if (wERR_FLOW_TIMEOUT) begin // Indicate timeout error during power failure flow, go to ST_ERROR directly
                            rstate                  <= ST_ERROR;
                        end else begin // MBVR failure flow
                            rStartTimer_T55         <= HIGH;
                            if (wDoneTimer_T55L) begin // Motherhood VR failure
                                rstate              <= ST_CPU_MEM;
                                rS0_PWROK_CPU0      <= LOW;
                                rS0_PWROK_CPU1      <= LOW;
                                rStartTimer_T55     <= LOW;
                                rStartTimer_T56     <= HIGH;
                            end
                        end
                    end else if (wPWR_DOWN_TOTAL) begin // In power down flow
                        rstate                  <= ST_CPU_PWRGD;
                        rRST_CPU0_RESET_N       <= LOW;
                        rStartTimer_T27         <= HIGH;
                    end else if (wPLTRST_POS && (wDoneTimer_1ms || !rStartTimer_1ms)) begin  // Platform is out of reset and timer done, go to next state
                        rstate                  <= ST_PLATFORM_ON;
                        rRST_CPU0_RESET_N       <= HIGH;
                        rPLTRST_NEGEDGE_N       <= LOW;
                        rSURPRISE_POSEDGE       <= LOW;
                        rStartTimer_1ms         <= LOW;
                    end else if (rPLTRST_NEGEDGE_N) begin
                        rRST_CPU0_RESET_N       <= LOW;
                    end else if (rSURPRISE_POSEDGE) begin // Warm reset triggered by BMC
                        rRST_CPU0_RESET_N       <= LOW;
                        rStartTimer_1ms         <= HIGH;
                    end
                end // case: ST_CPU_RESET

                ST_PLATFORM_ON: begin
                    rcount                          <= LOW;
                    CurrentTime_Masterfub           <= Runtime;
                    rPLTRST_POS                     <= LOW;
                    oADR_EN                         <= rADR_EN;                                     // Enable ADR if jumper is not set on board
                    if (wMBVR_ERR || wERR_FLOW_TIMEOUT) begin // Power failure
                        if (wERR_FLOW_TIMEOUT) begin // Indicate timeout error during power failure flow, go to ST_ERROR directly
                            rstate                  <= ST_ERROR;
                        end else begin // MBVR failure flow
                            rstate                  <= ST_CPU_RESET;
                            rRST_CPU0_RESET_N       <= LOW;
                            oPWRGD_CPU0              <= LOW;                                         // T54: max 1 us delay between CPU RESET# de-assert and CPU PWRGD de-assert
                            rStartTimer_T55         <= HIGH;
                        end
                    end else if (wRUNTIME_PWRDWN) begin // Runtime power down indication
                        rstate                      <= ST_CPU_RESET;
                        if (rTHERMTRIP_NEGEDGE_N) begin // If thermal trip, T33 timer start
                            rStartTimer_T33         <= HIGH;
                        end if (!wFM_GLBRST_WARN_N || rFM_GLOBAL_RESET_POSEDGE) begin
                            CurrentTime_Masterfub   <= GLOBAL_RESET;
                        end else if (wPWR_DOWN_NORMAL) begin
                            CurrentTime_Masterfub   <= COLD_RESET;
                        end else if (rPLTRST_NEGEDGE_N) begin
                            CurrentTime_Masterfub   <= WARM_RESET;
                        end else begin
                            CurrentTime_Masterfub   <= Runtime;
                        end
                    end
                end // case: ST_PLATFORM_ON

                ST_ERROR: begin	
                    rRST_CPU0_RESET_N               <= LOW;
                    oPWRGD_CPU0                      <= LOW;
                    rS0_PWROK_CPU0                  <= LOW;
                    rS0_PWROK_CPU1                  <= LOW;
                    rDDR_PowerDown_En               <= HIGH;
                    oCPU_MEM_EN                     <= LOW;
                    oCPU0_AUX_EN                    <= LOW;
                    oCPU1_AUX_EN                    <= LOW;
                    rAUX_PWRGD_CPU0                 <= LOW;
                    rAUX_PWRGD_CPU1                 <= LOW;
                    oPSU_EN                         <= LOW;
                    if (iSCM_BMC_FLT) begin // Indicate which type of error happened
                        pwr_err_source              <= ERR_SCM_AUX;
                    end else if (iCPU_AUX_FLT) begin
                        pwr_err_source              <= ERR_LCPU_AUX;
                    end else if (rFM_GLBRST_WARN_NEGEDGE_N && rcount) begin	
                        pwr_err_source              <= ERR_GLBRST_S5;
                    end else if (rTHERMTRIP_NEGEDGE_N) begin
                        pwr_err_source              <= ERR_THERMTRIP;
                    end else if ((iPSU_FLT && !(rADR_EN && iPSU_PWROK_FLT)) || iCPU_PWR_FLT || iCPU0_DIMM_FAULT || iCPU1_DIMM_FAULT) begin
                        pwr_err_source              <= ERR_MAIN_PWR;
                    end else if (iVR_PWROFF_TIMEOUT || iCPU_AUX_VR_PWROFF_ERR) begin
                        pwr_err_source              <= ERR_TIMEOUT;
                    end else if (iFORCE_TO_ENTER_ERR) begin	
                        pwr_err_source              <= ERR_FORCE_ENTER;
                    end else if (wDoneTimer_T33 || wDoneTimer_T55H || wDoneTimer_T56H) begin
                        pwr_err_source              <= ERR_MBVR_TIMEOUT;
                    end else if (rHPM_STBY_EN_NEGEDGE) begin
                        pwr_err_source              <= ERR_LTPI_BROKEN;
                    end else if (rSTBY_PWRGD_FLT || iSOCKET_REMOVED) begin
                        pwr_err_source              <= ERR_OTHER;
                    end
                    if (iPWR_RESTART && (pwr_err_source != ERR_SCM_AUX)) begin // BMC force to exit power failure state
                        oPWR_RESTART_CLEAR          <= HIGH;
                        oFORCE_TO_ENTER_ERR_CLEAR   <= HIGH;
                        oCLEAR_ERROR_STATE          <= HIGH;
                        pwr_err_source              <= ERR_NO;
                        if (iFM_SERIAL_BOOT) begin
                            rstate                  <= ST_BMC_BOOT;
                        end else if (!iFM_SERIAL_BOOT) begin
                            rstate                  <= ST_SCM_AUX;
                        end
                    end // case: ST_ERROR
                end

                ST_ADR: begin // Surprise pwr-dwn condition detected and ADR flow is enabled
                    if (iFM_SLP_S4_N && !wPWR_DOWN_TOTAL) begin // It could be emulated and wanted to recover for testing
                        rstate                  <= ST_LCPU_AUX;                     					 // Back to CPU AUX as sequence is powering up back again
                    end else begin
                        rstate                  <= rstate;
                    end
                end // case: ST_ADR

                default: begin
                    oCPU0_AUX_EN                <= LOW;
                    oCPU1_AUX_EN                <= LOW;
                    oPSU_EN                     <= LOW;
                    oCPU_MEM_EN                 <= LOW;
                    oADR_EN                     <= LOW;
                    oADR_RELEASE                <= LOW;
                    rS0_PWROK_CPU0              <= LOW;
                    rS0_PWROK_CPU1              <= LOW;
                    oPWRGD_CPU0                  <= LOW;
                    rAUX_PWRGD_CPU0             <= LOW;
                    rAUX_PWRGD_CPU1             <= LOW;
                    rcount                      <= LOW;
                    rDDR_PowerDown_En           <= LOW;
                    rRST_CPU0_RESET_N           <= LOW;
                    rFM_GLBRST_WARN_NEGEDGE_N   <= LOW;
                    rFM_GLBRST_WARN_N           <= LOW;
                    rPLTRST_NEGEDGE_N           <= LOW;
                    rPLTRST_POS                 <= LOW;
                    rPLTRST_N                   <= LOW;
                    rStartTimer_T27             <= LOW;
                    rStartTimer_T28             <= LOW;
                    rStartTimer_T31             <= LOW;
                    rStartTimer_T32             <= LOW;
                    rStartTimer_T33             <= LOW;
                    rStartTimer_1ms             <= LOW;
                    rStartTimer_T55             <= LOW;
                    rStartTimer_T56             <= LOW;
                    rTHERMTRIP_NEGEDGE_N        <= LOW;
                    rSURPRISE_RESET0            <= LOW;
                    rSURPRISE_RESET1            <= LOW;
                    rFM_GLOBAL_RESET0           <= LOW;
                    rFM_GLOBAL_RESET1           <= LOW;
                    rSURPRISE_POSEDGE           <= LOW;
                    oCLEAR_ERROR_STATE          <= LOW;
                    oPWR_RESTART_CLEAR          <= LOW;
                    oFORCE_TO_ENTER_ERR_CLEAR   <= LOW;

                    rstate                      <= ST_INIT;
                    pwr_err_source              <= ERR_NO;
                    CurrentTime_Masterfub       <= Runtime;
                end // case: default
            endcase
        end
    end

/*************************************************************************************************************
 * Instances                                                                                                 *
 *************************************************************************************************************/
    // T16: min 100 ms timer, from PVCCINFAON PWRGD assertion to S0_PWROK assertion
    delay #(.COUNT(T_100mS_2M)) 
        Timer100ms_T16 (
            .iClk    ( iClk            ),
            .iRst    ( iRst_n          ),
            .iStart  ( wStartTimer_T16 ),
            .iClrCnt ( 1'b0            ),
            .oDone   ( wDoneTimer_T16  )
        );

    // T18: min 1 ms timer, from CPU_REFCLK_RDY assertion to CPU_PWRGD assertion
    delay #(.COUNT(T_2_1mS_2M))
        Timer1ms_T18 (
            .iClk    ( iClk                ),
            .iRst    ( iRst_n              ),
            .iStart  (iFM_CPU0_REFCLK_RDY&&(iFM_CPU1_REFCLK_RDY||iFM_CPU1_SKTOCC_LVT3_PLD_N) && rS0_PWROK_CPU0 && (rS0_PWROK_CPU1 || iFM_CPU1_SKTOCC_LVT3_PLD_N)),
            .iClrCnt ( 1'b0                ),
            .oDone   ( wDoneTimer_T18      )
        );

    // T27: min 2 ms timer, from RESET# assertion to CPU_PWRGD de-assertion
    delay #(.COUNT(T_2mS_2M)) 
        Timer2ms_T27 (
            .iClk    ( iClk            ),
            .iRst    ( iRst_n          ),
            .iStart  ( wStartTimer_T27 ),
            .iClrCnt ( 1'b0            ),
            .oDone   ( wDoneTimer_T27  )
        );

    // T28: min 1 ms timer, from CPU_PWRGD de-assertion to S0_PWROK de-assertion
    delay #(.COUNT(T_1mS_2M)) 
        Timer1ms_T28 (
            .iClk    ( iClk            ),
            .iRst    ( iRst_n          ),
            .iStart  ( wStartTimer_T28 ),
            .iClrCnt ( 1'b0            ),
            .oDone   ( wDoneTimer_T28  )
        );

    // T31: min 100 us timer, from S0_PWROK de-assertion to non-legacy CPU AUX_PWRGD de-assertion
    delay #(.COUNT(T_100uS_2M)) 
        Timer100us_T31 (
            .iClk    ( iClk            ),
            .iRst    ( iRst_n          ),
            .iStart  ( wStartTimer_T31 ),
            .iClrCnt ( 1'b0            ),
            .oDone   ( wDoneTimer_T31  )
        );

    // T32: min 5 ms timer, from legacy CPU AUX_PWRGD de-assertion to legacy CPU AUX_PWRGD re-assertion
    delay #(.COUNT(T_5mS_2M)) 
        Timer5ms_T32 (
            .iClk    ( iClk            ),
            .iRst    ( iRst_n          ),
            .iStart  ( wStartTimer_T32 ),
            .iClrCnt ( 1'b0            ),
            .oDone   ( wDoneTimer_T32  )
        );

    // T33: max 500 ms watchdog, from thermtrip# assertion to VCCFA_EHV PWRGD de-assertion
    delay #(.COUNT(T_500mS_2M)) 
        Timer500ms_T33 (
            .iClk    ( iClk            ),
            .iRst    ( iRst_n          ),
            .iStart  ( wStartTimer_T33 ),
            .iClrCnt ( 1'b0            ),
            .oDone   ( wDoneTimer_T33  )
        );

    // T??: min 1 ms timer, from surprise reset assertion to reboot
    delay #(.COUNT(T_1mS_2M)) 
        Timer1ms (
            .iClk    ( iClk            ),
            .iRst    ( iRst_n          ),
            .iStart  ( wStartTimer_1ms ),
            .iClrCnt ( 1'b0            ),
            .oDone   ( wDoneTimer_1ms  )
        );

    // T_55: min 2 us timer, from CPU_PWRGD de-assertion to S0_PWROK de-assertion during MBVR failure flow
    delay #(.COUNT(T_2uS_2M)) 
        TimerT55L (
            .iClk    ( iClk            ),
            .iRst    ( iRst_n          ),
            .iStart  ( wStartTimer_T55 ),
            .iClrCnt ( 1'b0            ),
            .oDone   ( wDoneTimer_T55L )
        );

    // T_55: max 10 us timer, from CPU_PWRGD de-assertion to S0_PWROK de-assertion during MBVR failure flow
    delay #(.COUNT(T_10uS_2M)) 
        TimerT55H (
            .iClk    ( iClk            ),
            .iRst    ( iRst_n          ),
            .iStart  ( wStartTimer_T55 ),
            .iClrCnt ( 1'b0            ),
            .oDone   ( wDoneTimer_T55H )
        );

    // T_56: min 2 us timer, from S0_PWROK de-assertion to AUX_PWRGD de-assertion during MBVR failure flow
    delay #(.COUNT(T_2uS_2M)) 
        TimerT56L (
            .iClk    ( iClk            ),
            .iRst    ( iRst_n          ),
            .iStart  ( wStartTimer_T56 ),
            .iClrCnt ( 1'b0            ),
            .oDone   ( wDoneTimer_T56L )
        );

    // T_56: max 10 us timer, from S0_PWROK de-assertion to AUX_PWRGD de-assertion during MBVR failure flow
    delay #(.COUNT(T_10uS_2M)) 
        TimerT56H (
            .iClk    ( iClk            ),
            .iRst    ( iRst_n          ),
            .iStart  ( wStartTimer_T56 ),
            .iClrCnt ( 1'b0            ),
            .oDone   ( wDoneTimer_T56H )
        );

    // Delay between SLPS3# and SLPS4# to filter the glitch of wS3Indication
    delay #(.COUNT(T_1mS_2M)) 
        Timer1msB(
            .iClk    ( iClk                          ),
            .iRst    ( iRst_n                        ),
            .iStart  ( !iFM_SLP_S3_N && iFM_SLP_S4_N ),
            .iClrCnt ( 1'b0                          ),
            .oDone   ( wDoneTimer_1msB               )
        );

endmodule
